﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Collections;
using System.Data;
using System.Reflection;
using System.Reflection.Emit;
using System.Data.OleDb;
using System.Linq.Expressions;
using System.Data.Common;


    public static class StringExtend
    {
        #region 字符串转化为整形
        public static int ToInt(this string str)
        {
            if (string.IsNullOrEmpty(str))
                throw new ArgumentNullException("字符串为空");

            int result = 0;
            if (!int.TryParse(str, out result))
            {
                throw new ArgumentNullException("转型失败!");
            }
            return result;
        } 
        #endregion
        #region 正则验证
        /// <summary>
        /// 校验字符串是否只包含字母与数字
        /// </summary>
        /// <param name="toVerified">需要校验的字符串</param>
        /// <returns>true表示符合要求，false表示不符合要求</returns>
        public static bool IsOnlyLetterAndDigit(this string str)
        {
            if (string.IsNullOrEmpty(str))
                return false;
            Regex rx = new Regex(@"^[a-zA-Z0-9-]*$");
            return rx.IsMatch(str.Trim(), 0);
        }
        /// <summary>
        /// 检验是否是整数
        /// </summary>
        /// <param name="str">需要检验的字符串</param>
        /// <returns>是否为整数：true是整数，false非整数</returns>
        public static bool IsInt(this string str)
        {
            if (string.IsNullOrEmpty(str))
                return false;

            Regex rx = new Regex(@"^[0123456789]+$");
            return rx.IsMatch(str);
        }
        /// <summary>
        /// 校验是否为正的浮点数
        /// </summary>
        /// <param name="price">需要检验的字符串</param>
        /// <returns>是否为正浮点，是返回true，否则返回false</returns>
        public static bool IsFloat(this string str)
        {
            if (string.IsNullOrEmpty(str))
                return false;

            Regex rx = new Regex(@"^[0-9]*(.)?[0-9]+$", RegexOptions.IgnoreCase);
            return rx.IsMatch(str.Trim());
        }
        /// <summary>
        /// 检验是否为数字
        /// </summary>
        /// <param name="str">需要检验的字符串</param>
        /// <returns>是否为数字：true代表是，false代表否</returns>
        public static bool IsNumber(this string str)
        {
            if (string.IsNullOrEmpty(str))
                return false;
            Regex rx = new Regex(@"^[+-]?[0123456789]*[.]?[0123456789]*$");
            return rx.IsMatch(str);
        }
        /// <summary>
        /// 检验字符串是否为日期时间
        /// </summary>
        /// <param name="str">需要检验的字符串</param>
        /// <returns>是否为日期时间：true代表是，false代表否</returns>
        public static bool IsDateTime(this string str)
        {
            if (string.IsNullOrEmpty(str))
                return false;
            Regex rx = new Regex(@"^[ ]*[012 ]?[0123456789]?[0123456789]{2}[ ]*[-]{1}[ ]*[01]?[0123456789]{1}[ ]*[-]{1}[ ]*[0123]?[0123456789]{1}[ ]*[012]?[0123456789]{1}[ ]*[:]{1}[ ]*[012345]?[0123456789]{1}[ ]*[:]{1}[ ]*[012345]?[0123456789]{1}[ ]*$");
            return rx.IsMatch(str);
        }
        /// <summary>
        /// 检验字符串是否为邮政编码
        /// </summary>
        /// <param name="str">需要检验的字符串</param>
        /// <returns>是否为邮政编码：true代表是，false代表否</returns>
        public static bool IsZip(this string str)
        {
            if (string.IsNullOrEmpty(str))
                return false;
            Regex rx = new Regex(@"^[0123456789]{6}$");
            return rx.IsMatch(str);
        }
        /// <summary>
        /// 检验字符串是否为身份证号
        /// </summary>
        /// <param name="str">需要检验的字符串</param>
        /// <returns>是否为身份证号：true代表是，false代表否</returns>
        public static bool IsIDCard(this string str)
        {
            if (string.IsNullOrEmpty(str))
                return false;
            Regex rx = new Regex(@"^[0123456789]{15,18}$");
            return rx.IsMatch(str);
        }
        /// <summary>
        /// 检验字符串是否为电子邮件
        /// </summary>
        /// <param name="str">需要检验的字符串</param>
        /// <returns>是否为电子邮件：true代表是，false代表否</returns>
        public static bool IsEmail(this string str)
        {
            if (string.IsNullOrEmpty(str))
                return false;
            Regex rx = new Regex(@"w+([-+.]w+)*@w+([-.]w+)*.w+([-.]w+)*");
            return rx.IsMatch(str);
        }
        /// <summary>
        /// 检验字符串是否为中国地区的电话号码
        /// </summary>
        /// <param name="str">需要检验的字符串</param>
        /// <returns>是否为中国地区的电话号码：true代表是，false代表否</returns>
        public static bool IsPhoneNumber(this string str)
        {
            if (string.IsNullOrEmpty(str))
                return false;
            Regex rx = new Regex(@"((d{3,4})|d{3,4}-)?d{7,8}(-d{3})*");
            return rx.IsMatch(str);
        }
        /// <summary>
        /// 判断是否存在中文和全角字符
        /// </summary>
        /// <param name="str">需要检验的字符串</param>
        /// <returns>存在中文和全角字符：true代表是，false代表否</returns>
        public static bool IsChinese(this string str)
        {
            if (string.IsNullOrEmpty(str))
                return false;
            Regex rx = new Regex(@"[^\x00-\xff]");
            return rx.IsMatch(str);
        }
        /// <summary>
        /// 检验字符串是否为双字节字符(包括汉字)
        /// </summary>
        /// <param name="str">需要检验的字符串</param>
        /// <returns>是否为双字节字符：true代表是，false代表否</returns>
        public static bool IsDoubleByteChar(this string str)
        {
            if (string.IsNullOrEmpty(str))
                return false;
            Regex rx = new Regex(@"[^x00-xff]");
            return rx.IsMatch(str);
        }
        /// <summary>
        /// 检验字符串是否为URL地址
        /// </summary>
        /// <param name="str">需要检验的字符串</param>
        /// <returns>是否为URL地址：true代表是，false代表否</returns>
        public static bool IsURLAddress(this string str)
        {
            if (string.IsNullOrEmpty(str))
                return false;
            Regex rx = new Regex(@"[a-zA-z]+://[^s]*");
            return rx.IsMatch(str);
        }
        /// <summary>
        /// 检验字符串是否为IP地址
        /// </summary>
        /// <param name="str">需要检验的字符串</param>
        /// <returns>是否为IP地址：true代表是，false代表否</returns>
        public static bool IsIPAddress(this string str)
        {
            if (string.IsNullOrEmpty(str))
                return false;
            Regex rx = new Regex(@"d+.d+.d+.d+");
            return rx.IsMatch(str);
        }
        #endregion
        #region 过滤HTML
        /// <summary>
        /// 过滤html
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static string FilerHTML(this string str)
        {
            if (str != "")
            {
                return Regex.Replace(str, "<[^>]*>", "");
            }
            else
            {
                return "";
            }
        }
        #endregion
        #region 正则替换
        /// <summary>
        /// 正则替换
        /// </summary>
        /// <param name="oldStr"></param>
        /// <param name="pattern"></param>
        /// <param name="newStr"></param>
        /// <returns></returns>
        public static string RegexReplace(this string oldStr, string pattern, string newStr)
        {
            Regex r = new Regex(pattern, RegexOptions.IgnoreCase);
            return r.Replace(oldStr, newStr);
        }
        #endregion
        #region 截取字符
        public static string Substring(this string str, int length, string suffix)
        {
            if (string.IsNullOrEmpty(str))
                return "";

            if (str.Length <= length)
            {
                return str;
            }
            if (string.IsNullOrEmpty(suffix) || suffix.Length > length)
            {
                str = str.Substring(0, length);
            }
            else
            {
                str = str.Substring(0, length - suffix.Length);
            }
            return str;


        }
        #endregion
        #region 获取后缀
        public static string GetExt(this string str) 
        {
            if (string.IsNullOrEmpty(str))
                return "";

            int index = str.LastIndexOf('.');
            if (index != -1)
            {
                return str.Substring(index);
            }
            else 
            {
                return str;
            }
        }
        #endregion
        #region 获取文件名
        public static string GetFileName(this string str)
        {
            if (string.IsNullOrEmpty(str))
                return "";

            int start = str.LastIndexOf('/');
            int end = str.LastIndexOf('.');
            if (start != -1 && end != -1)
            {
                return str.Substring(start + 1, end);
            }
            else
            {
                return str;
            }
        }
        public static string GetFileNameWidthExt(this string str)
        {
            if (string.IsNullOrEmpty(str))
                return "";

            int start = str.LastIndexOf('/');
            if (start != -1)
            {
                return str.Substring(start + 1);
            }
            else
            {
                return str;
            }
        }
        #endregion

    }
    public static class DataTableExtend
    {
        /// <summary>
        /// Emit绑定
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="dt"></param>
        /// <returns></returns>
        delegate object DataTableEmitDelegate(DataRow dr);
        public static List<T> ToList<T>(this DataTable dt)
        {

            MethodInfo getValueMethod = typeof(DataRow).GetMethod("get_Item", new Type[] { typeof(int) });
            MethodInfo isDBNullMethod = typeof(DataRow).GetMethod("IsNull", new Type[] { typeof(int) });


            //生成一个方法
            DynamicMethod method = new DynamicMethod("BindToEntityListForEmit", typeof(T), new Type[] { typeof(DataRow) }, typeof(T), true);
            //开始构造方法的主体IL代码
            ILGenerator generator = method.GetILGenerator();
            //生成一个本地变量 result
            LocalBuilder result = generator.DeclareLocal(typeof(T));
            //实例化本地变量 result
            generator.Emit(OpCodes.Newobj, typeof(T).GetConstructor(Type.EmptyTypes));
            //设置堆栈中的值 到本地变量
            generator.Emit(OpCodes.Stloc, result);



            for (int i = 0; i < dt.Columns.Count; i++)
            {
                PropertyInfo pi = typeof(T).GetProperty(dt.Columns[i].ColumnName);
                //定义一个标记 这里是如果是null的时候跳转使用的标记
                Label endIfLabel = generator.DefineLabel();
                if (pi != null && pi.GetSetMethod() != null)
                {
                    //加载参数1 即DataRow  到堆栈
                    generator.Emit(OpCodes.Ldarg_0);
                    //加载整形 i 到堆栈
                    generator.Emit(OpCodes.Ldc_I4, i);
                    //调用方DataRow.IsNull(i) 并把返回值保存到堆栈中 真=1 假=0
                    generator.Emit(OpCodes.Callvirt, isDBNullMethod);
                    //判断堆栈里面的值是否为真 真=1 假=0 如果不是那么跳转到endIfLabel标记
                    generator.Emit(OpCodes.Brtrue, endIfLabel);
                    //加载本地变量result 到堆栈
                    generator.Emit(OpCodes.Ldloc, result);
                    //加载参数1 即DataRow  到堆栈
                    generator.Emit(OpCodes.Ldarg_0);
                    //加载整形 i 到堆栈
                    generator.Emit(OpCodes.Ldc_I4, i);
                    //调用方法DataRow.get_Item(i) 并把返回值保存到堆栈中
                    generator.Emit(OpCodes.Callvirt, getValueMethod);
                    //拆箱操作 堆栈里面的值
                    generator.Emit(OpCodes.Unbox_Any, pi.PropertyType);
                    //调用属性的Set方法 把堆栈中的值设置到属性中
                    generator.Emit(OpCodes.Callvirt, pi.GetSetMethod());
                    //null标记 如果数据为空那么程序将会直接跳转到这个标记这里
                    generator.MarkLabel(endIfLabel);
                }
            }

            //加载本地变量 到堆栈
            generator.Emit(OpCodes.Ldloc, result);
            generator.Emit(OpCodes.Ret);
            DataTableEmitDelegate de = (DataTableEmitDelegate)method.CreateDelegate(typeof(DataTableEmitDelegate));




            List<T> list = new List<T>();
            foreach (DataRow row in dt.Rows)
            {
                T t = (T)de(row);
                list.Add(t);
            }
            return list;
        }
        public static List<T> ToList<T>(this DataTable dt, Expression<Func<DataRow, T>> predicate)
        {
            Delegate de = predicate.Compile();
            List<T> list = new List<T>();
            foreach (DataRow row in dt.Rows)
            {
                T t = (T)de.DynamicInvoke(row);
                list.Add(t);
            }
            return list;
        }
        delegate object DbDataReaderEmitDelegate(DbDataReader dr);
        public static List<T> ToList<T>(this DbDataReader dr)
        {

            MethodInfo getValueMethod = typeof(DataRow).GetMethod("GetValue", new Type[] { typeof(int) });
            MethodInfo isDBNullMethod = typeof(DataRow).GetMethod("IsDBNull", new Type[] { typeof(int) });


            //生成一个方法
            DynamicMethod method = new DynamicMethod("BindToEntityListForEmit", typeof(T), new Type[] { typeof(DbDataReader) }, typeof(T), true);
            //开始构造方法的主体IL代码
            ILGenerator generator = method.GetILGenerator();
            //生成一个本地变量 result
            LocalBuilder result = generator.DeclareLocal(typeof(T));
            //实例化本地变量 result
            generator.Emit(OpCodes.Newobj, typeof(T).GetConstructor(Type.EmptyTypes));
            //设置堆栈中的值 到本地变量
            generator.Emit(OpCodes.Stloc, result);

            for (int i = 0; i < dr.FieldCount; i++)
            {
                PropertyInfo pi = typeof(T).GetProperty(dr.GetName(i));
                //定义一个标记 这里是如果是null的时候跳转使用的标记
                Label endIfLabel = generator.DefineLabel();
                if (pi != null && pi.GetSetMethod() != null)
                {
                    //加载参数1 即DataRow  到堆栈
                    generator.Emit(OpCodes.Ldarg_0);
                    //加载整形 i 到堆栈
                    generator.Emit(OpCodes.Ldc_I4, i);
                    //调用方DataRow.IsNull(i) 并把返回值保存到堆栈中 真=1 假=0
                    generator.Emit(OpCodes.Callvirt, isDBNullMethod);
                    //判断堆栈里面的值是否为真 真=1 假=0 如果不是那么跳转到endIfLabel标记
                    generator.Emit(OpCodes.Brtrue, endIfLabel);
                    //加载本地变量result 到堆栈
                    generator.Emit(OpCodes.Ldloc, result);
                    //加载参数1 即DataRow  到堆栈
                    generator.Emit(OpCodes.Ldarg_0);
                    //加载整形 i 到堆栈
                    generator.Emit(OpCodes.Ldc_I4, i);
                    //调用方法DataRow.get_Item(i) 并把返回值保存到堆栈中
                    generator.Emit(OpCodes.Callvirt, getValueMethod);
                    //拆箱操作 堆栈里面的值
                    generator.Emit(OpCodes.Unbox_Any, pi.PropertyType);
                    //调用属性的Set方法 把堆栈中的值设置到属性中
                    generator.Emit(OpCodes.Callvirt, pi.GetSetMethod());
                    //null标记 如果数据为空那么程序将会直接跳转到这个标记这里
                    generator.MarkLabel(endIfLabel);
                }
            }

            //加载本地变量 到堆栈
            generator.Emit(OpCodes.Ldloc, result);
            generator.Emit(OpCodes.Ret);
            DbDataReaderEmitDelegate de = (DbDataReaderEmitDelegate)method.CreateDelegate(typeof(DbDataReaderEmitDelegate));




            List<T> list = new List<T>();

            while (dr.Read()) 
            {
                T t = (T)de(dr);
                list.Add(t);
            }

           
            return list;
        }
        public static List<T> ToList<T>(this DbDataReader dr, Expression<Func<DbDataReader, T>> predicate)
        {
            Delegate de = predicate.Compile();
            List<T> list = new List<T>();
            while (dr.Read()) 
            {
                T t = (T)de.DynamicInvoke(dr);
                list.Add(t);
            }
            return list;
        }


    }

    public class Member 
    {
        public int MyProperty { get; set; }
    }


    /// <summary>
    /// 数据库类型转换
    /// </summary>
    public static class TypeExtend
    {

        public static Type ToCSharpType(this SqlDbType sqlType)
        {
            switch (sqlType)
            {
                case SqlDbType.BigInt:
                    return typeof(Int64);
                case SqlDbType.Binary:
                    return typeof(Object);
                case SqlDbType.Bit:
                    return typeof(Boolean);
                case SqlDbType.Char:
                    return typeof(String);
                case SqlDbType.DateTime:
                    return typeof(DateTime);
                case SqlDbType.Decimal:
                    return typeof(Decimal);
                case SqlDbType.Float:
                    return typeof(Double);
                case SqlDbType.Image:
                    return typeof(Object);
                case SqlDbType.Int:
                    return typeof(Int32);
                case SqlDbType.Money:
                    return typeof(Decimal);
                case SqlDbType.NChar:
                    return typeof(String);
                case SqlDbType.NText:
                    return typeof(String);
                case SqlDbType.NVarChar:
                    return typeof(String);
                case SqlDbType.Real:
                    return typeof(Single);
                case SqlDbType.SmallDateTime:
                    return typeof(DateTime);
                case SqlDbType.SmallInt:
                    return typeof(Int16);
                case SqlDbType.SmallMoney:
                    return typeof(Decimal);
                case SqlDbType.Text:
                    return typeof(String);
                case SqlDbType.Timestamp:
                    return typeof(Object);
                case SqlDbType.TinyInt:
                    return typeof(Byte);
                case SqlDbType.Udt:
                    return typeof(Object);
                case SqlDbType.UniqueIdentifier:
                    return typeof(Object);
                case SqlDbType.VarBinary:
                    return typeof(Object);
                case SqlDbType.VarChar:
                    return typeof(String);
                case SqlDbType.Variant:
                    return typeof(Object);
                case SqlDbType.Xml:
                    return typeof(Object);
                default:
                    return null;
            }

        }
        public static SqlDbType ToSqlDbType(this Type t)
        {
            TypeCode tc = Type.GetTypeCode(t);
            switch (tc)
            {
                case TypeCode.Boolean:
                    return SqlDbType.Bit;
                //case TypeCode.Byte:
                //    break;
                case TypeCode.Char:
                    return SqlDbType.Char;
                //case TypeCode.DBNull:
                //    break;
                case TypeCode.DateTime:
                    return SqlDbType.DateTime;
                case TypeCode.Decimal:
                    return SqlDbType.Decimal;
                case TypeCode.Double:
                    return SqlDbType.Float;
                //case TypeCode.Empty:
                //    break;
                case TypeCode.Int16:
                    return SqlDbType.SmallInt;
                case TypeCode.Int32:
                    return SqlDbType.Int;
                case TypeCode.Int64:
                    return SqlDbType.BigInt;
                //case TypeCode.Object:
                //    break;
                //case TypeCode.SByte:
                //    break;
                case TypeCode.Single:
                    return SqlDbType.Real;
                case TypeCode.String:
                    return SqlDbType.Char;
                //case TypeCode.UInt16:
                //    break;
                //case TypeCode.UInt32:
                //    break;
                //case TypeCode.UInt64:
                //    break;
                default:
                    return new SqlDbType();
            }

        }

        public static Type ToCSharpType(this OleDbType oleDbType)
        {
            switch (oleDbType)
            {
                case OleDbType.BSTR:
                    return typeof(Object);
                case OleDbType.BigInt:
                    return typeof(Int64);
                case OleDbType.Binary:
                    return typeof(Object);
                case OleDbType.Boolean:
                    return typeof(Boolean);
                case OleDbType.Char:
                    return typeof(Char);
                case OleDbType.Currency:
                    return typeof(Decimal);
                case OleDbType.DBDate:
                    return typeof(DateTime);
                case OleDbType.DBTime:
                    return typeof(DateTime);
                case OleDbType.DBTimeStamp:
                    return typeof(DateTime);
                case OleDbType.Date:
                    return typeof(DateTime);
                case OleDbType.Decimal:
                    return typeof(Object);
                case OleDbType.Double:
                    return typeof(Double);
                case OleDbType.Empty:
                    return typeof(Nullable);
                case OleDbType.Error:
                    return typeof(Exception);
                case OleDbType.Filetime:
                    return typeof(DateTime);
                case OleDbType.Guid:
                    return typeof(Guid);
                case OleDbType.IDispatch:
                    return typeof(Object);
                case OleDbType.IUnknown:
                    return typeof(Object);
                case OleDbType.Integer:
                    return typeof(Int32);
                case OleDbType.LongVarBinary:
                    return typeof(Object);
                case OleDbType.LongVarChar:
                    return typeof(String);
                case OleDbType.LongVarWChar:
                    return typeof(String);
                case OleDbType.Numeric:
                    return typeof(Decimal);
                case OleDbType.PropVariant:
                    return typeof(Object);
                case OleDbType.Single:
                    return typeof(Single);
                case OleDbType.SmallInt:
                    return typeof(Int16);
                case OleDbType.TinyInt:
                    return typeof(SByte);
                case OleDbType.UnsignedBigInt:
                    return typeof(UInt64);
                case OleDbType.UnsignedInt:
                    return typeof(UInt32);
                case OleDbType.UnsignedSmallInt:
                    return typeof(UInt16);
                case OleDbType.UnsignedTinyInt:
                    return typeof(Byte);
                case OleDbType.VarBinary:
                    return typeof(Array);
                case OleDbType.VarChar:
                    return typeof(String);
                case OleDbType.VarNumeric:
                    return typeof(Decimal);
                case OleDbType.VarWChar:
                    return typeof(String);
                case OleDbType.Variant:
                    return typeof(Object);
                case OleDbType.WChar:
                    return typeof(String);
                default:
                    return typeof(Object);
            }

        }
        public static OleDbType ToOleDbType(this Type t) 
        {
            
            TypeCode tc = Type.GetTypeCode(t);
            switch (tc)
            {
                case TypeCode.Boolean:
                    return OleDbType.Boolean;
                //case TypeCode.Byte:
                //    break;
                case TypeCode.Char:
                    return OleDbType.Char;
                //case TypeCode.DBNull:
                //    break;
                case TypeCode.DateTime:
                    return OleDbType.Date;
                case TypeCode.Decimal:
                    return OleDbType.Decimal;
                case TypeCode.Double:
                    return OleDbType.Double;
                //case TypeCode.Empty:
                //    break;
                case TypeCode.Int16:
                    return OleDbType.SmallInt;
                case TypeCode.Int32:
                    return OleDbType.Integer;
                case TypeCode.Int64:
                    return OleDbType.BigInt;
                //case TypeCode.Object:
                //    break;
                //case TypeCode.SByte:
                //    break;
                case TypeCode.Single:
                    return OleDbType.Single;
                case TypeCode.String:
                    return OleDbType.Char;
                case TypeCode.UInt16:
                    return OleDbType.UnsignedSmallInt;
                case TypeCode.UInt32:
                    return OleDbType.UnsignedInt;
                case TypeCode.UInt64:
                    return OleDbType.UnsignedBigInt;
                default:
                    return new OleDbType();
            }

        }
       
    }


